/**
 * 复制指令
 * @description 复制指令，绑定在元素上后，点击元素即可复制指令绑定的文本内容
 * @usage v-copy="要复制的文本内容"
 * @param {*} el 指令绑定的元素
 * @param {*} binding 指令相关的信息对象
 * @param {*} vnode Vue编译生成的虚拟节点
 * @param {*} oldVnode 上一个虚拟节点，仅在更新和销毁时可用
 */

import { message } from 'ant-design-vue'
import type { DirectiveBinding } from 'vue'

const copyDirective = {
  mounted(el: HTMLElement, binding: DirectiveBinding) {
    // 保存指令绑定的初始值
    ;(el as any).__copyValue__ = binding.value

    // 处理函数读取 el 上的 __copyValue__（保证拿到最新值）
    const handler = async (e: Event) => {
      e.stopPropagation() // 阻止事件冒泡

      let text = (el as any).__copyValue__ // 获取指令绑定的值
      // 如果不小心传了 ref（极端情况），尝试取 .value
      if (text && typeof text === 'object' && 'value' in text) text = (text as any).value // 如果绑定的值是一个对象，则取对象的 value 属性

      if (text === undefined || text === null || text === '') {
        message.error('没有要复制的内容')
        return
      }

      try {
        // 一开始就是localhost,单单使用了 Clipboard API，没用考虑到是否支持http
        // 直到和后端联调用了 http 后 发现Clipboard API 失效了才加上了这个判断并且重构了一次
        // 在“安全上下文”中运行 必须是 https:// 协议，或 http://localhost。如果是 http:// 的非本地地址，navigator.clipboard 直接不存在。
        // 优先使用 Clipboard API（需要 HTTPS 或 localhost）
        if (navigator.clipboard && navigator.clipboard.writeText) {
          await navigator.clipboard.writeText(String(text))
          message.success('复制成功')
          return
        }

        // 否则使用传统 textarea + execCommand 回退
        // 如果 Clipboard API 不可用，则使用 document.execCommand
        const textarea = document.createElement('textarea')
        textarea.value = String(text)
        textarea.setAttribute('readonly', '') // 设置只读
        textarea.style.position = 'absolute' // 设置绝对定位
        textarea.style.left = '-9999px' // 设置到屏幕外
        document.body.appendChild(textarea) // 添加到 body 中
        textarea.select() // 选中内容

        const successful = document.execCommand('copy') // 执行复制命令
        document.body.removeChild(textarea) // 移除 textarea

        if (!successful) throw new Error('execCommand 复制失败')

        message.success('复制成功')
      } catch (err) {
        console.log('复制失败:', err)
        message.error('复制失败(查看控制台)')
      }
    }

    ;(el as any).__copyHandler__ = handler // 存储事件处理函数，方便移除

    el.addEventListener('click', handler)
  },
  updated(el: HTMLElement, binding: DirectiveBinding) {
    ;(el as any).__copyValue__ = binding.value // 更新存储的值
  },

  unmounted(el: HTMLElement) {
    const handler = (el as any).__copyHandler__ // 获取存储的事件处理函数
    if (handler) {
      el.removeEventListener('click', handler) // 移除事件监听
    }
    delete (el as any).__copyValue__ // 删除存储的值
    delete (el as any).__copyHandler__ // 删除存储的事件处理函数
  },
}

export default copyDirective
